FileSaver.js ➔ click   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 2
1
(function (global, factory) {
2
  if (typeof define === "function" && define.amd) {
3
    define([], factory);
4
  } else if (typeof exports !== "undefined") {
5
    factory();
6
  } else {
7
    var mod = {
8
      exports: {}
9
    };
10
    factory();
11
    global.FileSaver = mod.exports;
12
  }
13
})(this, function () {
14
  "use strict";
15
16
  /*
17
  * FileSaver.js
18
  * A saveAs() FileSaver implementation.
19
  *
20
  * By Eli Grey, http://eligrey.com
21
  *
22
  * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
23
  * source  : http://purl.eligrey.com/github/FileSaver.js
24
  */
25
  // The one and only way of getting global scope in all enviorment
26
  // https://stackoverflow.com/q/3277182/1008999
27
  var _global = function () {
28
    // some use content security policy to disable eval
29
    try {
30
      return Function('return this')() || (42, eval)('this');
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
Security Performance introduced by
Calls to eval are slow and potentially dangerous, especially on untrusted code. Please consider whether there is another way to achieve your goal.
Loading history...
Performance Best Practice introduced by
Using new Function() to create a function is slow and difficult to debug. Such functions do not create a closure. Consider using another way to define your function.
Loading history...
31
    } catch (e) {
32
      // every global should have circular reference
33
      // used for checking if someone writes var window = {}; var self = {}
34
      return typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : this;
35
    }
36
  }();
37
38
  function bom(blob, opts) {
39
    if (typeof opts === 'undefined') opts = {
40
      autoBom: false
41
    };else if (typeof opts !== 'object') {
42
      console.warn('Depricated: Expected third argument to be a object');
43
      opts = {
44
        autoBom: !opts
45
      };
46
    } // prepend BOM for UTF-8 XML and text/* types (including HTML)
47
    // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
48
49
    if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
50
      return new Blob([String.fromCharCode(0xFEFF), blob], {
51
        type: blob.type
52
      });
53
    }
54
55
    return blob;
56
  }
57
58
  function download(url, name, opts) {
59
    var xhr = new XMLHttpRequest();
60
    xhr.open('GET', url);
61
    xhr.responseType = 'blob';
62
63
    xhr.onload = function () {
64
      saveAs(xhr.response, name, opts);
65
    };
66
67
    xhr.onerror = function () {
68
      console.error('could not download file');
69
    };
70
71
    xhr.send();
72
  }
73
74
  function corsEnabled(url) {
75
    var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
76
77
    xhr.open('HEAD', url, false);
78
    xhr.send();
79
    return xhr.status >= 200 && xhr.status <= 299;
80
  } // `a.click()` don't work for all browsers (#465)
81
82
83
  function click(node) {
84
    try {
85
      node.dispatchEvent(new MouseEvent('click'));
86
    } catch (e) {
87
      var evt = document.createEvent('MouseEvents');
88
      evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
89
      node.dispatchEvent(evt);
90
    }
91
  }
92
93
  var saveAs = _global.saveAs || // probably in some web worker
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable saveAs already seems to be declared on line 94. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
94
  typeof window !== 'object' || window !== _global ? function saveAs() {}
95
  /* noop */
96
  // Use download attribute first if possible (#193 Lumia mobile)
97
  : 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, opts) {
98
    var URL = _global.URL || _global.webkitURL;
99
    var a = document.createElement('a');
100
    name = name || blob.name || 'download';
101
    a.download = name;
102
    a.rel = 'noopener'; // tabnabbing
103
    // TODO: detect chrome extensions & packaged apps
104
    // a.target = '_blank'
105
106
    if (typeof blob === 'string') {
107
      // Support regular links
108
      a.href = blob;
109
110
      if (a.origin !== location.origin) {
111
        corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
0 ignored issues
show
Bug introduced by
The call to click seems to have too many arguments starting with a.target = "_blank".
Loading history...
112
      } else {
113
        click(a);
114
      }
115
    } else {
116
      // Support blobs
117
      a.href = URL.createObjectURL(blob);
118
      setTimeout(function () {
119
        URL.revokeObjectURL(a.href);
120
      }, 4E4); // 40s
121
122
      setTimeout(function () {
123
        click(a);
124
      }, 0);
125
    }
126
  } // Use msSaveOrOpenBlob as a second approch
127
  : 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
128
    name = name || blob.name || 'download';
129
130
    if (typeof blob === 'string') {
131
      if (corsEnabled(blob)) {
132
        download(blob, name, opts);
133
      } else {
134
        var a = document.createElement('a');
135
        a.href = blob;
136
        a.target = '_blank';
137
        setTimeout(function () {
138
          clikc(a);
139
        });
140
      }
141
    } else {
142
      navigator.msSaveOrOpenBlob(bom(blob, opts), name);
143
    }
144
  } // Fallback to using FileReader and a popup
145
  : function saveAs(blob, name, opts, popup) {
146
    // Open a popup immediately do go around popup blocker
147
    // Mostly only avalible on user interaction and the fileReader is async so...
148
    popup = popup || open('', '_blank');
149
150
    if (popup) {
151
      popup.document.title = popup.document.body.innerText = 'downloading...';
152
    }
153
154
    if (typeof blob === 'string') return download(blob, name, opts);
155
    var force = blob.type === 'application/octet-stream';
156
157
    var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
158
159
    var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
160
161
    if ((isChromeIOS || force && isSafari) && typeof FileReader === 'object') {
162
      // Safari doesn't allow downloading of blob urls
163
      var reader = new FileReader();
164
165
      reader.onloadend = function () {
166
        var url = reader.result;
167
        url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
168
        if (popup) popup.location.href = url;else location = url;
169
        popup = null; // reverse-tabnabbing #460
170
      };
171
172
      reader.readAsDataURL(blob);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
173
    } else {
174
      var URL = _global.URL || _global.webkitURL;
175
      var url = URL.createObjectURL(blob);
176
      if (popup) popup.location = url;else location.href = url;
177
      popup = null; // reverse-tabnabbing #460
178
179
      setTimeout(function () {
180
        URL.revokeObjectURL(url);
181
      }, 4E4); // 40s
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
182
    }
183
  };
184
  // openpsa-modified: See https://github.com/eligrey/FileSaver.js/issues/475
185
  _global.saveAs = saveAs.saveAs = saveAs;
186
});
187